/*
 *
 * Copyright 2017, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>

#include "src/core/ext/client_channel/client_channel.h"
#include "src/core/ext/lb_policy/grpclb/grpclb_channel.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/support/string.h"

grpc_channel *grpc_lb_policy_grpclb_create_lb_channel(
    grpc_exec_ctx *exec_ctx, const char *lb_service_target_addresses,
    grpc_client_channel_factory *client_channel_factory,
    grpc_channel_args *args) {
  grpc_channel *lb_channel = grpc_client_channel_factory_create_channel(
      exec_ctx, client_channel_factory, lb_service_target_addresses,
      GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, args);
  return lb_channel;
}

grpc_channel_args *get_lb_channel_args(grpc_exec_ctx *exec_ctx,
                                       grpc_slice_hash_table *targets_info,
                                       const grpc_channel_args *args) {
  /* We strip out the channel arg for the LB policy name, since we want
   * to use the default (pick_first) in this case.
   *
   * We also strip out the channel arg for the resolved addresses, since
   * that will be generated by the name resolver used in the LB channel.
   * Note that the LB channel will use the sockaddr resolver, so this
   * won't actually generate a query to DNS (or some other name service).
   * However, the addresses returned by the sockaddr resolver will have
   * is_balancer=false, whereas our own addresses have is_balancer=true.
   * We need the LB channel to return addresses with is_balancer=false
   * so that it does not wind up recursively using the grpclb LB policy,
   * as per the special case logic in client_channel.c.
   *
   * Lastly, we also strip out the channel arg for the server URI,
   * since that will be different for the LB channel than for the parent
   * channel (the client channel factory will re-add this arg with
   * the right value). */
  static const char *keys_to_remove[] = {
      GRPC_ARG_LB_POLICY_NAME, GRPC_ARG_LB_ADDRESSES, GRPC_ARG_SERVER_URI};
  return grpc_channel_args_copy_and_remove(args, keys_to_remove,
                                           GPR_ARRAY_SIZE(keys_to_remove));
}
